package com.ruoyi.order.service.impl;

import java.io.IOException;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;
import java.security.Signature;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.businessOrder.domain.dto.RefundApplyDto;
import com.ruoyi.businessOrder.domain.dto.RefundAuditDto;
import com.ruoyi.common.config.WxPaymentConfig;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.enums.wxpay.WxApiType;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.distributionConfig.domain.DistributionConfig;
import com.ruoyi.distributionConfig.service.IDistributionConfigService;
import com.ruoyi.distributionLog.service.IDistributionLogService;
import com.ruoyi.distributionRelation.service.IDistributionRelationCacheService;
import com.ruoyi.distributor.domain.DistributionUser;
import com.ruoyi.distributor.service.IDistributionUserService;
import com.ruoyi.dto.PayDto;
import com.ruoyi.goods.domain.Goods;
import com.ruoyi.goods.service.IGoodsService;
import com.ruoyi.goodsDetail.domain.OrderGoodsDetail;
import com.ruoyi.goodsDetail.service.IOrderGoodsDetailService;
import com.ruoyi.guest.domain.Guest;
import com.ruoyi.guest.service.IGuestService;
import com.ruoyi.income.domain.DistributionIncome;
import com.ruoyi.income.service.IDistributionIncomeService;
import com.ruoyi.order.domain.OrderCreateDTO;
import com.ruoyi.order.domain.OrderItemDTO;
import com.ruoyi.order.service.IRemoteOrderService;
import com.ruoyi.payLog.domain.PayLogs;
import com.ruoyi.payLog.service.IPayLogsService;
import com.ruoyi.rebateRule.domain.RebateRule;
import com.ruoyi.rebateRule.service.IRebateRuleService;
import com.ruoyi.refundInfo.domain.RefundInfo;
import com.ruoyi.refundInfo.service.IRefundInfoService;
import com.ruoyi.relationOrder.domain.DistributionOrderRelation;
import com.ruoyi.relationOrder.service.IDistributionOrderRelationService;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.verificationDetail.domain.VerificationDetail;
import com.ruoyi.verificationDetail.service.IVerificationDetailService;
import com.ruoyi.wallet.domain.DistributionWallet;
import com.ruoyi.wallet.service.IDistributionWalletService;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.order.mapper.OrderMapper;
import com.ruoyi.order.domain.Order;
import com.ruoyi.order.service.IOrderService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 订单信息Service业务层处理
 * 
 * @author ruoyi
 * @date 2025-06-03
 */
@Service
public class OrderServiceImpl implements IOrderService, IRemoteOrderService
{
    private static final Logger log = LoggerFactory.getLogger(OrderServiceImpl.class);

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private ISysUserService userService;

    @Autowired
    private IGoodsService goodsService;

    @Autowired
    private IOrderGoodsDetailService orderGoodsDetailService;

    @Autowired
    private IRefundInfoService refundInfoService;

    @Autowired
    private IGuestService guestService;

    @Autowired
    private IPayLogsService payLogsService;

    @Autowired
    private WxPaymentConfig wxPaymentConfig;

    @Autowired
    private CloseableHttpClient wxPaymentClient;

    @Autowired
    private IOrderService orderService;

    @Autowired
    private IDistributionUserService distributionUserService;

    @Autowired
    private IRebateRuleService rebateRuleService;

    @Autowired
    private IDistributionOrderRelationService distributionOrderRelationService;

    @Autowired
    private IDistributionIncomeService distributionIncomeService;

    @Autowired
    private IDistributionWalletService distributionWalletService;

    @Autowired
    private IDistributionLogService distributionLogService;

    @Autowired
    private IDistributionConfigService distributionConfigService;

    @Autowired
    private IDistributionRelationCacheService distributionRelationCacheService;

    // 添加这一行
    @Autowired
    private IVerificationDetailService verificationDetailService;


    /**
     * 查询订单信息
     * 
     * @param orderId 订单信息主键
     * @return 订单信息
     */
    @Override
    public Order selectOrderByOrderId(Long orderId)
    {
        return orderMapper.selectOrderByOrderId(orderId);
    }

    /**
     * 查询订单信息列表
     * 
     * @param order 订单信息
     * @return 订单信息
     */
    @Override
    public List<Order> selectOrderList(Order order)
    {
        return orderMapper.selectOrderList(order);
    }

    /**
     * 新增订单信息
     * 
     * @param order 订单信息
     * @return 结果
     */
    @Override
    public int insertOrder(Order order)
    {
        // 根据当前登录的用户id, 获取用户信息
        Long userId = SecurityUtils.getUserId();
        if (userId == null) {
            log.error("无法获取当前用户ID");
            throw new ServiceException("无法获取当前用户信息");
        }
        // 设置用户ID（使用从SecurityUtils获取的userId）
        order.setUserId(userId);

        // 查询顾客信息
        Guest guest = guestService.selectGuestByGuestId(order.getGuestId());
        if (guest == null) {
            log.error("顾客信息不存在，关联的用户ID：{}", order.getUserId());
            throw new ServiceException("顾客信息不存在");
        }

        // 设置顾客ID（使用从guest获取的guestId）
        order.setGuestId(guest.getGuestId());

        // 确保订单状态初始化
        if (order.getMasterStatus() == null) {
            order.setMasterStatus("0"); // 0=待支付
        }
        if (order.getStatus() == null) {
            order.setStatus("0");
        }

        // 生成订单号（如果未提供）
        if (order.getOrderCode() == null || order.getOrderCode().isEmpty()) {
            order.setOrderCode(IdUtils.generateOrderCode());
        }

        // 设置创建时间
        order.setCreateTime(DateUtils.getNowDate());

        // 移除有问题的商品查询代码
        // Goods goods = goodsService.selectGoodsByGoodsId(order.getGoodsId());

        return orderMapper.insertOrder(order);
    }

    /**
     * 修改订单信息
     * 
     * @param order 订单信息
     * @return 结果
     */
    @Override
    public int updateOrder(Order order)
    {
        order.setUpdateTime(DateUtils.getNowDate());
        return orderMapper.updateOrder(order);
    }

    /**
     * 批量删除订单信息
     * 
     * @param orderIds 需要删除的订单信息主键
     * @return 结果
     */
    @Override
    public int deleteOrderByOrderIds(Long[] orderIds)
    {
        return orderMapper.deleteOrderByOrderIds(orderIds);
    }

    /**
     * 删除订单信息信息
     * 
     * @param orderId 订单信息主键
     * @return 结果
     */
    @Override
    public int deleteOrderByOrderId(Long orderId)
    {
        return orderMapper.deleteOrderByOrderId(orderId);
    }

    /**
     * 创建订单信息
     *
     * @param payDto
     * @param platform
     * @return Order
     */
    public Order createOrder(PayDto payDto, String platform) {
        // 查询顾客
        return null;
    }


    /**
     * 查询下单用户的上级分销员
     *
     * @param userId 下单用户ID
     * @return 上级分销员信息，如果没有上级则返回null
     */
    @Override
    public DistributionUser getParentDistributor(Long userId) {
        try {
            // 1. 首先检查用户本身是否是分销员
            DistributionUser currentUser = distributionUserService.selectDistributionUserByUserId(userId);
            if (currentUser == null) {
                log.info("用户{}不是分销员", userId);
                return null;
            }

            // 2. 获取用户的上级分销员ID
            Long fatherId = currentUser.getFatherId();
            if (fatherId == null || fatherId == 0L) {
                log.info("分销员{}没有上级", currentUser.getDistributorId());
                return null;
            }

            // 3. 查询上级分销员信息
            DistributionUser parentDistributor = distributionUserService.selectDistributionUserByDistributorId(fatherId);
            if (parentDistributor == null) {
                log.warn("上级分销员{}不存在", fatherId);
                return null;
            }

            // 4. 验证上级分销员状态
            if (!"0".equals(parentDistributor.getStatus()) || !"0".equals(parentDistributor.getDelFlag())
                    || !"1".equals(parentDistributor.getAuthStatus())) {
                log.warn("上级分销员{}状态异常", fatherId);
                return null;
            }

            return parentDistributor;
        } catch (Exception e) {
            log.error("查询用户{}的上级分销员时发生异常", userId, e);
            return null;
        }
    }

    /**
     * 创建订单信息
     *
     * @param createDTO
     * @return
     */
    @Override
    public Order createFullOrder(OrderCreateDTO createDTO) {
        // 1. 验证基础数据
        if (createDTO.getItems() == null || createDTO.getItems().isEmpty()) {
            throw new ServiceException("订单中必须包含商品");
        }
        if (createDTO.getGuestId() == null) {
            throw new ServiceException("必须指定顾客ID");
        }

        // 2. 创建主订单
        Order order = new Order();
        // 初始化订单信息：【必填信息】
        Long userId = SecurityUtils.getUserId();
        order.setUserId(userId);
        order.setGuestId(createDTO.getGuestId());
        order.setOrderCode(IdUtils.generateOrderCode());
        order.setOrderType(createDTO.getOrderType());
        // 初始化业务订单信息：【选填信息】
        order.setCreateTime(new Date());
        // 主状态（0=待支付, 1=已支付, 2=待处理, 3=处理中, 4=已完成, 5=已取消）
        order.setMasterStatus("0"); // 0=待支付
        order.setStatus("0");

        // 3. 设置分销关联ID：优先使用前端传递的分销员ID，其次检查缓存中的分销关系，最后查询用户的上级分销员
        try {
            // 优先检查createDTO中是否包含分销员ID（扫码进入）
            Long distributorId = createDTO.getDistributorId();
            if (distributorId != null && distributorId > 0) {
                // 验证分销员ID是否有效
                DistributionUser specifiedDistributor = distributionUserService.selectDistributionUserByDistributorId(distributorId);
                if (specifiedDistributor != null && "0".equals(specifiedDistributor.getStatus())
                        && "0".equals(specifiedDistributor.getDelFlag())
                        && "1".equals(specifiedDistributor.getAuthStatus())) {
                    // 设置前端传递的分销员ID到订单中
                    order.setDistributorId(distributorId);
                    log.info("订单关联扫码分销员ID: {}", distributorId);
                } else {
                    log.warn("指定的分销员ID无效或状态异常: {}", distributorId);
                    // 如果指定分销员无效，则检查缓存中的分销关系
                    setCachedDistributorIfExists(order, userId, createDTO.getItems());
                }
            } else {
                // 如果createDTO中没有分销员ID，则检查缓存中的分销关系
                setCachedDistributorIfExists(order, userId, createDTO.getItems());
            }
        } catch (Exception e) {
            log.warn("设置分销关联ID时发生异常: {}", e.getMessage());
            // 即使检查失败，也不影响订单创建流程，订单将不关联分销
        }

        // 3. 计算总金额并准备商品详情
        BigDecimal totalAmount = BigDecimal.ZERO;
        List<OrderGoodsDetail> detailList = new ArrayList<>();

        for (OrderItemDTO item : createDTO.getItems()) {
            // 查询商品最新信息（确保使用下单时的价格）
            Goods goods = goodsService.selectGoodsByGoodsId(item.getGoodsId());
            if (goods == null) {
                throw new ServiceException("商品不存在: " + item.getGoodsId());
            }

            // 检查库存
            if (goods.getTotalStock() < item.getQuantity()) {
                throw new ServiceException("商品【" + goods.getGoodsName() + "】库存不足");
            }

            // 创建商品快照
            OrderGoodsDetail detail = new OrderGoodsDetail();
            // 初始化业务订单信息：【必填信息】
            detail.setGoodsId(item.getGoodsId());
            // 详情编号
            detail.setDetailCode(IdUtils.generateOrderDetailCode());
            // 初始化业务订单信息：【选填信息】
            detail.setGoodsName(goods.getGoodsName());      // 商品名称快照
            detail.setMainImage(goods.getImgUrl());         // 商品图片快照
            detail.setUnitPrice(goods.getSalePrice());      // 下单时单价
            detail.setQuantity(item.getQuantity().longValue());
            detail.setSubtotal(goods.getSalePrice().multiply(new BigDecimal(item.getQuantity())));
            // detail.setSpecs("标准规格");  // 可根据需要修改
            detail.setStatus("0");


            detailList.add(detail);
            totalAmount = totalAmount.add(detail.getSubtotal());
        }
        // 4. 设置主订单总金额
        order.setTotalAmount(totalAmount);
        order.setCreateTime(new Date());
        order.setCreateBy(SecurityUtils.getUsername());
        // 过期时间
        order.setExpireTime(DateUtils.addMinutes(DateUtils.getNowDate(), 15)); // 15分钟后过期
        // 5. 保存主订单
        int orderResult = insertOrder(order);

        if (orderResult == 0) {
            throw new ServiceException("创建主订单失败");
        }
        // 6. 保存商品详情（关联主订单ID）
        for (OrderGoodsDetail detail : detailList) {
            detail.setOrderId(order.getOrderId());
            detail.setCreateTime(new Date());
            detail.setCreateBy(SecurityUtils.getUsername());
            orderGoodsDetailService.insertOrderGoodsDetail(detail);
        }

        // 7. 扣减库存（使用乐观锁防止超卖）
        for (OrderItemDTO item : createDTO.getItems()) {
            Goods goods = goodsService.selectGoodsByGoodsId(item.getGoodsId());
            goods.setTotalStock(goods.getTotalStock() - item.getQuantity());
            goods.setVersion(goods.getVersion() + 1);  // 乐观锁版本号+1

            if (goodsService.updateGoods(goods) <= 0) {
                throw new ServiceException("库存更新失败，请重试");
            }
        }

        // 8. 保存扩展信息（如收货人信息）
        saveOrderExtra(order, createDTO);

        // 同步创建支付日志
        PayLogs payLogs = new PayLogs();
        // 初始化订单支付记录信息：【必填信息】
        payLogs.setGoodsOrderId(order.getOrderId()); // 商品订单ID
        payLogs.setAmount(order.getTotalAmount()); // 实付金额 元为单位（支付金额从订单数据中获取）
        // 初始化订单支付记录信息：【选填信息】
        payLogs.setPaymentStatus("0"); // 支付状态：0=待支付 1=已支付 2=支付失败

        // 插入支付日志
        try {
            int rows1 = payLogsService.insertPayLogs(payLogs);
            if (rows1 <= 0) {
                throw new ServiceException("订单支付记录信息插入失败");
            }
        } catch (Exception e) {
            log.error("订单支付记录信息插入失败，订单信息：{}, 错误详情：{}", payLogs, e.getMessage());
            throw e;
        }

        // 9. 如果订单有关联的分销员，则创建分销订单关联记录
        if (order.getDistributorId() != null) {
            try {
                // 创建分销订单关联记录
                DistributionOrderRelation relationOrder = new DistributionOrderRelation();
                relationOrder.setOrderId(order.getOrderId());
                relationOrder.setOrderCode(order.getOrderCode());

                // 设置分销员ID 需要判断是什么层级的分销员，如果分销员上级则还需设置second_distributor_id
                // 查询当前分销员的上级分销员（二级分销）
                DistributionUser firstDistributor = distributionUserService.selectDistributionUserByDistributorId(order.getDistributorId());
                if (firstDistributor != null && firstDistributor.getFatherId() != null && firstDistributor.getFatherId() > 0) {
                    // 设置二级分销员ID
                    relationOrder.setSecondDistributorId(firstDistributor.getFatherId());
                }
                // 设置一级分销员ID
                relationOrder.setFirstDistributorId(order.getDistributorId());

                // 获取分销配置中的结算周期天数
                DistributionConfig config = distributionConfigService.selectDistributionConfigByConfigId(1L);
                if (config != null && config.getSettlementDays() != null) {
                    // 设置结算时间（当前时间 + 结算天数）
                    LocalDateTime settlementTime = LocalDateTime.now().plusDays(config.getSettlementDays());
                    relationOrder.setSettlementTime(Date.from(settlementTime.atZone(ZoneId.systemDefault()).toInstant()));
                } else {
                    // 默认30天
                    LocalDateTime settlementTime = LocalDateTime.now().plusDays(30);
                    relationOrder.setSettlementTime(Date.from(settlementTime.atZone(ZoneId.systemDefault()).toInstant()));
                }

                relationOrder.setDistributionStatus("0"); // 0-待支付

                relationOrder.setStatus("0"); // 0-上架状态
                relationOrder.setDelFlag("0"); // 未删除

                // 设置创建信息
                relationOrder.setCreateBy(SecurityUtils.getUsername());
                relationOrder.setCreateTime(new Date());

                // 插入分销订单关联记录
                int relationResult = distributionOrderRelationService.insertDistributionOrderRelation(relationOrder);
                if (relationResult <= 0) {
                    log.error("创建分销订单关联记录失败，订单ID: {}", order.getOrderId());
                } else {
                    log.info("成功创建分销订单关联记录，订单ID: {}", order.getOrderId());
                    // 添加分销操作日志
                    try {
                        com.ruoyi.distributionLog.domain.DistributionLog distributionLog = new com.ruoyi.distributionLog.domain.DistributionLog();
                        distributionLog.setLogCode("LOG" + System.currentTimeMillis()); // 日志流水号
                        distributionLog.setDistributorId(order.getDistributorId()); // 分销员ID
                        distributionLog.setLogType("1"); // 日志类型：1-绑定
                        distributionLog.setAction("订单创建"); // 操作动作说明
                        distributionLog.setChangeObject("订单"); // 变更对象
                        // 添加变更详情
                        distributionLog.setChangeDetail("{\"message\":\"订单创建成功，订单号：" + order.getOrderCode() + "\"}"); // 变更详情
                        // 添加来源单号
                        distributionLog.setSourceCode(order.getOrderCode()); // 来源单号

                        distributionLog.setStatus("0"); // 状态（0=上架 1=下架）

                        distributionLog.setCreateBy(SecurityUtils.getUsername());
                        distributionLog.setCreateTime(new Date());

                        // 调用分销日志服务插入日志
                        distributionLogService.insertDistributionLog(distributionLog);
                        log.info("分销操作日志记录已准备，订单ID: {}", order.getOrderId());
                    } catch (Exception e) {
                        log.error("创建分销操作日志时发生异常，订单ID: {}", order.getOrderId(), e);
                    }
                }
            } catch (Exception e) {
                log.error("创建分销订单关联记录时发生异常，订单ID: {}", order.getOrderId(), e);
                // 不影响主流程，继续执行
            }
        }

        return order;
    }

    /**
     * 保存订单扩展信息
     *
     * @param order
     * @param createDTO
     */
    private void saveOrderExtra(Order order, OrderCreateDTO createDTO) {
        Map<String, Object> extraData = new HashMap<>();
        extraData.put("receiverName", createDTO.getReceiverName());
        extraData.put("receiverPhone", createDTO.getReceiverPhone());
        extraData.put("receiverAddress", createDTO.getReceiverAddress());

        order.setOrderExtra(JSON.toJSONString(extraData));
        updateOrder(order);  // 更新主订单的扩展信息
    }

    // 订单基础校验
    private void validateOrderForPayment(Order order) {
        // 订单基础校验
        if (order == null) {
            throw new ServiceException("订单不存在");
        }

        // 订单超时校验
        if (order.getExpireTime().before(new Date())) {
            throw new ServiceException("订单已过期");
        }

        // 订单状态校验
//        if (!"0".equals(order.getPayStatus())) {
//            throw new ServiceException("订单状态异常");
//        }

    }

    /**
     * 生成支付结束时间，遵循 RFC3339 格式
     * @return 格式示例：2025-06-11T12:30:00+08:00
     */
    private String generateTimeExpire() {
        // 默认设置为当前时间 + 15 分钟（可按业务需求调整）
        ZonedDateTime expireTime = ZonedDateTime.now(ZoneId.of("Asia/Shanghai")).plusMinutes(15);
        return expireTime.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
    }

    /**
     * 支付状态检查
     *
     * @param orderId 订单ID
     */
    private void checkPaymentStatus(Long orderId) {
        try {
            Order order = selectOrderByOrderId(orderId);
            if (order != null && "1".equals(order.getMasterStatus())) {
                log.info("订单已支付，无需关闭，orderId: {}", orderId);
                return;
            }

            // 检查订单是否已关闭或已退款等最终状态
            if (order != null && ("2".equals(order.getMasterStatus()) || "4".equals(order.getMasterStatus()))) {
                log.info("订单已处于最终状态，无需继续检查，orderId: {}", orderId);
                return;
            }

            // 订单未支付，调用关闭订单接口
            log.info("订单支付超时，开始关闭订单，orderId: {}", orderId);
            HashMap<String, Object> closeResult = miniAppCloseOrder(orderId);
            boolean success = (boolean) closeResult.get("success");
            // boolean closed = (boolean) closeResult.get("closed");
            // boolean userPaying = (boolean) closeResult.get("userPaying");
            if (success) {
                log.info("订单关闭成功，orderId: {}", orderId);
            } else {
                log.error("订单关闭失败，orderId: {}", orderId);
            }
        } catch (Exception e) {
            log.error("支付状态检查失败，订单ID: {}", orderId, e);
        }
    }


    /**
     * 启动定时任务检查支付状态
     *
     * @param orderId 订单ID
     */
    private void scheduleOrderTimeoutTask(Long orderId) {
        try {
            Order order = selectOrderByOrderId(orderId);
            if (order == null) return;

            Date now = DateUtils.getNowDate();
            // 订单超时延时
            long timeoutDelay = order.getExpireTime().getTime() - now.getTime();

            // 修复点1：增加延迟校验
            if (timeoutDelay <= 0) {
                log.warn("订单{}已过期，立即执行超时检查", orderId);
                // 立即执行支付状态检查
                checkPaymentStatus(orderId);
                return;
            }

            // 修复点2：使用ScheduledExecutorService替代Timer
            ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
            executor.schedule(() -> {
                try {
                    checkPaymentStatus(orderId);
                } finally {
                    executor.shutdown();
                }
            }, timeoutDelay, TimeUnit.MILLISECONDS);

        } catch (Exception e) {
            log.error("定时任务调度失败，订单ID: {}", orderId, e);
        }
    }


    /**
     * 构建返回结果
     *
     * @param order 订单信息
     * @param result 微信返回结果
     * @return 构建结果
     */
    private HashMap<String, Object> buildResponse(Order order, Map<String, String> result) {
        HashMap<String, Object> map = new HashMap<>();
        // 预交易订单编号
        map.put("prepayId", result.get("prepay_id"));
        // 订单编号
        map.put("orderCode", order.getOrderCode());
        // 过期时间
        map.put("expireTime", order.getExpireTime().getTime());

        return map;
    }


    // 支付成功阶段的分销逻辑已经成功实现。让我来确认一下各个步骤：
    // 1. ✅ **接收支付平台回调** - 系统成功接收并处理了微信支付回调
    // 2. ✅ **更新普通订单为"已支付"** - 订单状态已从待支付(0)更新为已支付(1)
    // 3. ✅ **查询分销订单关联表** - 成功查询到订单的分销关联信息
    // 4. ✅ **计算返佣金额** - 根据规则计算出返佣金额0.0010
    // 5. ✅ **写入返佣收入表（状态=待结算）** - 成功插入返佣记录，状态为"1"(待结算)
    // 6. ✅ **更新分销员钱包待结算余额** - 成功将0.0010添加到分销员待结算余额中
    // 7. ✅ **同步更新分销订单关联表状态为"待结算"** - 成功更新分销订单关联状态为"1"(待结算)
    /**
     * 更新订单状态为已支付
     *
     * @param outTradeNo 商户订单号
     * @param transactionId 微信支付交易号
     * @param successTime 支付成功时间
     * @return 更新结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateOrderStatus(String outTradeNo, String transactionId, String successTime) {
        try {
            log.info("开始更新订单支付状态: outTradeNo={}, transactionId={}, successTime={}",
                    outTradeNo, transactionId, successTime);

            // 1. 根据订单号查询订单
            Order order = orderMapper.selectOrderByOrderCode(outTradeNo);
            if (order == null) {
                log.error("未找到对应订单: outTradeNo={}", outTradeNo);
                return false;
            }

            // 2. 检查订单状态，避免重复处理
            if ("1".equals(order.getMasterStatus())) {
                log.info("订单已处理为已支付状态，无需重复处理: orderId={}", order.getOrderId());
                return true;
            }

            // 3. 更新订单状态
            order.setMasterStatus("1"); // 已支付
            // order.setPayTime(DateUtils.parseDate(successTime)); // 支付时间（未获取）
            order.setPayTime(new Date()); // 支付时间
            order.setUpdateTime(new Date());

            // 生成核销码
            String verificationCode = generateVerificationCode(order.getOrderCode());
            order.setVerificationCode(verificationCode);
            // 初始化核销状态为待使用
            order.setVerificationStatus("0");

            int orderUpdateResult = orderMapper.updateOrder(order);
            if (orderUpdateResult <= 0) {
                log.error("更新订单状态失败: orderId={}", order.getOrderId());
                throw new ServiceException("更新订单状态失败");
            }

            // 4. 更新支付日志
            PayLogs payLogs = payLogsService.getPayLogsByGoodsOrderId(order.getOrderId());
            if (payLogs != null) {
                // payment_method 微信支付 支付方式
                payLogs.setPaymentMethod("1"); // 微信支付
                payLogs.setPaymentStatus("1"); // 已支付
                payLogs.setTransactionId(transactionId); // 微信交易号
                // payer_id 微信openid
                // payLogs.setPaymentTime(DateUtils.parseDate(successTime)); // 支付时间 （未获取）
                payLogs.setPaymentTime(new Date()); // 支付时间
                payLogs.setUpdateTime(new Date());
                int payLogUpdateResult = payLogsService.updatePayLogs(payLogs);
                if (payLogUpdateResult <= 0) {
                    log.error("更新支付日志失败: paymentId={}", payLogs.getPaymentId());
                    throw new ServiceException("更新支付日志失败");
                }
            }

            // 5. 可以在这里添加其他业务逻辑，比如：
            // 处理分销返佣逻辑
            processDistributionRebate(order);
            // - 增加用户积分
            // - 发送支付成功通知
            // - 更新库存等

            log.info("订单支付状态更新成功: orderId={}, transactionId={}", order.getOrderId(), transactionId);
            return true;

        } catch (Exception e) {
            log.error("更新订单支付状态异常: outTradeNo={}", outTradeNo, e);
            throw new ServiceException("处理支付结果失败: " + e.getMessage());
        }
    }

    /**
     * 生成核销码
     * 格式：订单号 + 5位随机字符串
     * @param orderCode 订单号
     * @return 核销码
     */
    private String generateVerificationCode(String orderCode) {
        // 生成5位随机字符串
        String randomStr = generateRandomString(5);
        // 限制订单号长度，总长度控制在合理范围内
        String shortOrderCode = orderCode.length() > 10 ? orderCode.substring(orderCode.length() - 10) : orderCode;
        return shortOrderCode + randomStr;
    }

        /**
     * 生成核销码
     * 格式：订单号 + 5位随机字符串
     * @param orderCode 订单号
     * @return 核销码
     */
    private String generateVerificationCode20(String orderCode) {
        // 生成5位随机字符串
        String randomStr = generateRandomString(5);
        // 固定总长度为20位，其中随机字符串占5位，订单号占15位
        if (orderCode.length() > 15) {
            orderCode = orderCode.substring(0, 15);
        } else if (orderCode.length() < 15) {
            // 如果订单号不足15位，在前面补0
            orderCode = String.format("%15s", orderCode).replace(' ', '0');
        }
        return orderCode + randomStr;
    }



    /**
     * 生成指定长度的随机字符串
     * @param length 长度
     * @return 随机字符串
     */
    private String generateRandomString(int length) {
        String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < length; i++) {
            sb.append(chars.charAt(random.nextInt(chars.length())));
        }
        return sb.toString();
    }

    /**
     * 处理分销返佣逻辑
     *
     * @param order 订单信息
     */
    private void processDistributionRebate(Order order) {
        try {
            log.info("开始处理分销返佣，订单ID: {}", order.getOrderId());

            // 1. 查询分销订单关联记录
            DistributionOrderRelation relationOrder = new DistributionOrderRelation();
            relationOrder.setOrderId(order.getOrderId());
            List<DistributionOrderRelation> relationList = distributionOrderRelationService.selectDistributionOrderRelationList(relationOrder);

            if (relationList == null || relationList.isEmpty()) {
                log.info("该订单无分销关联记录，订单ID: {}", order.getOrderId());
                return;
            }

            // 获取第一个分销订单关联记录，这里假定只有一个分销关联记录（实际应用中可能需要处理多个层级）
            DistributionOrderRelation relation = relationList.get(0);

            // 2. 检查分销状态是否为待支付
            if (!"0".equals(relation.getDistributionStatus())) {
                log.info("分销订单状态不是待支付，当前状态: {}，订单ID: {}", relation.getDistributionStatus(), order.getOrderId());
                return;
            }

            // 3. 获取分销配置，检查结算周期设置
            DistributionConfig config = distributionConfigService.selectDistributionConfigByConfigId(1L);
            boolean immediateSettlement = false;
            if (config != null && config.getSettlementDays() != null && config.getSettlementDays() == 0) {
                immediateSettlement = true;
                log.info("检测到结算周期为0，启用立即返佣模式");
            }

            // 4. 计算返佣金额并写入返佣收入表
            calculateAndSaveRebate(order, relation, immediateSettlement);

            if (immediateSettlement) {
                // 5. 如果结算周期为0，直接设置为已结算状态
                relation.setDistributionStatus("2"); // 已结算
                relation.setSettlementTime(new Date()); // 立即结算
                log.info("立即返佣模式：分销订单直接设置为已结算状态");
            } else {
                // 6. 如果结算周期不为0，设置为待结算状态
                relation.setDistributionStatus("1"); // 待结算

                // 设置结算时间（当前时间 + 结算天数）
                Long settlementDays = config != null && config.getSettlementDays() != null ?
                    config.getSettlementDays() : 7L; // 默认7天
                LocalDateTime settlementTime = LocalDateTime.now().plusDays(settlementDays);
                relation.setSettlementTime(Date.from(settlementTime.atZone(ZoneId.systemDefault()).toInstant()));
                log.info("常规返佣模式：设置{}天后结算", settlementDays);
            }

            // 更新分销订单关联表状态
            distributionOrderRelationService.updateDistributionOrderRelation(relation);

            log.info("分销返佣处理完成，订单ID: {}", order.getOrderId());
        } catch (Exception e) {
            log.error("处理分销返佣时发生异常，订单ID: {}", order.getOrderId(), e);
            // 不抛出异常，避免影响主流程
        }
    }

    /**
     * 计算返佣金额并保存到返佣收入表
     *
     * @param order 订单信息
     * @param relationOrder 分销订单关联信息
     * @param immediateSettlement 是否立即返佣
     */
    private void calculateAndSaveRebate(Order order, DistributionOrderRelation relationOrder, boolean immediateSettlement) {
        try {
            log.info("开始计算返佣金额，订单ID: {}", order.getOrderId());

            // 1. 处理一级分销员返佣
            if (relationOrder.getFirstDistributorId() != null) {
                DistributionUser firstDistributor = distributionUserService.selectDistributionUserByDistributorId(
                        relationOrder.getFirstDistributorId());
                if (firstDistributor != null) {
                    // 匹配返佣规则 relation_level 应该根据分销员关联表中的关系来匹配
                    RebateRule matchedRule = matchRebateRule(order, firstDistributor, "1");
                    if (matchedRule != null) {
                        // 计算返佣金额
                        BigDecimal rebateAmount = calculateRebateAmount(order, matchedRule);
                        // 判断返佣金额是否大于0，避免负数返佣
                        if (rebateAmount.compareTo(BigDecimal.ZERO) > 0) {
                            // 创建返佣收入记录
                            createDistributionIncome(order, firstDistributor, rebateAmount, "1", matchedRule, immediateSettlement);
                        }
                    }
                }
            }

            // 2. 处理二级分销员返佣
            if (relationOrder.getSecondDistributorId() != null) {
                DistributionUser secondDistributor = distributionUserService.selectDistributionUserByDistributorId(
                        relationOrder.getSecondDistributorId());
                if (secondDistributor != null) {
                    // 匹配返佣规则
                    RebateRule matchedRule = matchRebateRule(order, secondDistributor, "2");
                    if (matchedRule != null) {
                        // 计算返佣金额
                        BigDecimal rebateAmount = calculateRebateAmount(order, matchedRule);
                        if (rebateAmount.compareTo(BigDecimal.ZERO) > 0) {
                            // 创建返佣收入记录
                            createDistributionIncome(order, secondDistributor, rebateAmount, "2", matchedRule, immediateSettlement);
                        }
                    }
                }
            }

            log.info("返佣金额计算完成，订单ID: {}", order.getOrderId());
        } catch (Exception e) {
            log.error("计算返佣金额时发生异常，订单ID: {}", order.getOrderId(), e);
        }
    }

    /**
     * 计算返佣金额
     *
     * @param order 订单信息
     * @param rule 返佣规则
     * @return 返佣金额
     */
    private BigDecimal calculateRebateAmount(Order order, RebateRule rule) {
        try {
            BigDecimal rebateAmount = BigDecimal.ZERO;

            // 根据返佣类型计算
            if ("1".equals(rule.getRebateType())) {
                // 按比例返佣
                rebateAmount = order.getTotalAmount().multiply(rule.getRebateValue().divide(BigDecimal.valueOf(100), 2, BigDecimal.ROUND_HALF_UP));
            } else if ("2".equals(rule.getRebateType())) {
                // 按固定金额返佣
                rebateAmount = rule.getRebateValue();
            }

            // 确保返佣金额不超过订单金额
            if (rebateAmount.compareTo(order.getTotalAmount()) > 0) {
                rebateAmount = order.getTotalAmount();
            }

            return rebateAmount;
        } catch (Exception e) {
            log.error("计算返佣金额异常，订单ID: {}", order.getOrderId(), e);
            return BigDecimal.ZERO;
        }
    }


    /**
     * 创建返佣收入记录
     *
     * @param order 订单信息
     * @param distributor 分销员
     * @param rebateAmount 返佣金额
     * @param level 分销层级
     * @param rule 返佣规则
     * @param immediateSettlement 是否立即返佣
     */
    private void createDistributionIncome(Order order, DistributionUser distributor, BigDecimal rebateAmount,
                                         String level, RebateRule rule, boolean immediateSettlement) {
        try {

            // 创建返佣收入记录
            com.ruoyi.income.domain.DistributionIncome income = new com.ruoyi.income.domain.DistributionIncome();

            // 设置字段值
            income.setOrderId(order.getOrderId()); // 订单ID
            income.setOrderCode(order.getOrderCode()); // 订单编号
            income.setDistributorId(distributor.getDistributorId()); // 分销员ID

            income.setRebateAmount(rebateAmount); // 返佣金额
            income.setOrderAmount(order.getTotalAmount()); // 订单金额
            income.setRelationLevel(level); // 分销层级
            income.setRuleId(rule.getRuleId()); // 返佣规则ID
            // 根据是否立即返佣设置收入状态
            if (immediateSettlement) {
                income.setIncomeStatus("2"); // 已可用
            } else {
                income.setIncomeStatus("1"); // 待结算 状态：0-待计算 1-已计算(待结算) 2-已发放 3-已取消 4-已扣回
            }

            // 添加goods_id字段，从订单商品详情中获取
            OrderGoodsDetail goodsDetail = orderGoodsDetailService.selectOrderGoodsDetailByOrderId(order.getOrderId());
            if (goodsDetail != null) {
                income.setGoodsId(goodsDetail.getGoodsId());
            }

            // 其他字段设置
            income.setDelFlag("0");
            income.setVersion(1L);
            income.setCreateTime(new Date());
            income.setCreateBy("system"); // 使用系统用户，避免在异步回调中获取用户信息

            // 插入返佣收入记录
            distributionIncomeService.insertDistributionIncome(income);
            log.info("创建返佣收入记录成功，分销员ID: {}，返佣金额: {}，订单ID: {}",
                distributor.getDistributorId(), rebateAmount, order.getOrderId());

            // 更新分销员钱包余额
            DistributionWallet wallet = distributionWalletService.selectWalletByDistributorId(distributor.getDistributorId());
            if (wallet != null) {
                if (immediateSettlement) {
                    // 立即返佣：直接增加到可用余额
                    wallet.setAvailableBalance(
                        wallet.getAvailableBalance() != null ?
                        wallet.getAvailableBalance().add(rebateAmount) :
                        rebateAmount
                    );
                    log.info("立即返佣：更新分销员钱包可用余额成功，分销员ID: {}，增加金额: {}，订单ID: {}",
                        distributor.getDistributorId(), rebateAmount, order.getOrderId());
                } else {
                    // 常规返佣：增加到待结算余额
                    wallet.setPendingSettlementBalance(
                        wallet.getPendingSettlementBalance() != null ?
                        wallet.getPendingSettlementBalance().add(rebateAmount) :
                        rebateAmount
                    );
                    log.info("常规返佣：更新分销员钱包待结算余额成功，分销员ID: {}，增加金额: {}，订单ID: {}",
                        distributor.getDistributorId(), rebateAmount, order.getOrderId());
                }

                // 更新总收益
                wallet.setTotalIncome(
                    wallet.getTotalIncome() != null ?
                    wallet.getTotalIncome().add(rebateAmount) :
                    rebateAmount
                );

                wallet.setUpdateTime(new Date());
                wallet.setUpdateBy("system"); // 使用系统用户，避免在异步回调中获取用户信息
                distributionWalletService.updateDistributionWallet(wallet);
            }
        } catch (Exception e) {
            log.error("创建返佣收入记录时发生异常，分销员ID: {}，订单ID: {}",
                distributor.getDistributorId(), order.getOrderId(), e);
        }
    }




//    我已经为你的分销业务实现了微信支付分账接口，主要完成了以下工作：
//    在订单服务接口中添加了分账方法声明
//    在订单服务实现类中实现了分账逻辑，包括：
//    验证订单状态（必须是已支付订单）
//    获取微信支付交易号
//            检查是否为分销订单
//    构造分账请求参数
//            调用微信支付分账API
//    在订单控制器中添加了分账接口
//            在订单实体类中添加了分销员ID字段
//    修改了创建订单逻辑，支持记录分销员ID
//        在订单创建DTO中添加了分销员ID字段
//    分账功能的核心逻辑如下：
//    只有已支付的分销订单才能进行分账
//    分账请求包含微信支付订单号、商户分账单号、分账接收方列表等信息
//    分账接收方可为分销员（通过商户ID或OpenID接收）
//    分账金额可根据业务规则计算（示例中使用订单金额的10%）
//    支持解冻剩余未分资金


    /**
     * 小程序获取预支付id
     *
     * @param orderId 交易商品信息主键
     * @return 交易订单信息
     */
    @Override
    public HashMap<String, Object> miniAppGetPrePayId(Long orderId) throws Exception {

        log.info("发起支付请求, 获取预支付id");
        // 支付的前提，当前订单的业务订单信息和支付日志信息已经存在数据库中
        // 订单基础校验
        Order order = selectOrderByOrderId(orderId);
        validateOrderForPayment(order);

        // 获取商品订单详情
        OrderGoodsDetail detail = orderGoodsDetailService.selectOrderGoodsDetailByOrderId(orderId);

        // 支付幂等性校验 校验支付日志是否存在且状态为待支付
        // 订单支付日志基础校验
        PayLogs existingPayLogs = payLogsService.getPayLogsByGoodsOrderId(orderId);
        // 存在且状态不为待支付
        if (existingPayLogs != null) {
            // handleExistingPaymentLog(existingPayLogs, order);

            // 如果 prepayId 或 codeUrl 为空，重新调用微信下单
            // 空字符串会被误判为"非空"
            if (StringUtils.isNotEmpty(existingPayLogs.getPrepayId()))
            {
                // 重新调用微信统一下单接口
                HashMap<String, Object> map = new HashMap<>();
                map.put("prepayId", existingPayLogs.getPrepayId());
                map.put("orderCode", order.getOrderCode());
                map.put("expireTime", order.getExpireTime().getTime());
                return map;
            }
        }

        log.info("调用JSAPI/小程序统一下单API");
        // 【1】创建HTTP请求, 请求https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi JSAPI/小程序下单接口
        HttpPost httpPost = new HttpPost(wxPaymentConfig.getDomain().concat(WxApiType.JSAPI_PAY.getType()));

        // 【2】封装下单请求Body参数
        log.info("封装下单请求Body参数");
        // 创建JSON对象
        ObjectMapper objectMapper = new ObjectMapper();
        // 创建表单对象
        Map params = new HashMap<>();

        // 微信小程序下单请求, Body参数:
        // appid
        params.put("appid", wxPaymentConfig.getAppid());
        // mchid
        params.put("mchid", wxPaymentConfig.getMchId());
        // 商品描述
        params.put("description", detail.getGoodsName());
        // 订单号, 每次调用获取预支付订单编号时都生成一个新的微信交易编号
        params.put("out_trade_no", order.getOrderCode());
        // 支付结束时间（选填）
//        params.put("time_expire", generateTimeExpire());
        if (order.getExpireTime() != null) {
            // 使用订单原始过期时间
            params.put("time_expire", order.getExpireTime().toInstant()
                    .atZone(ZoneId.of("Asia/Shanghai"))
                    .format(DateTimeFormatter.ISO_OFFSET_DATE_TIME));
        } else {
            // 紧急情况回退机制
            params.put("time_expire", generateTimeExpire());
            log.warn("订单{}未设置过期时间，使用默认时间", orderId);
        }
        // 商户数据包（选填）

        // 支付回调地址
        // v2: "/wxpay/pay"
        // v3: "/wxpay/v3/pay"
        params.put("notify_url", wxPaymentConfig.getNotifyDomain() + "/wxpay/v3/pay");

        // 订单优惠标记（选填）
        params.put("goods_tag", "wdmGoodsTag");
        // 电子发票入口开放标识（选填）
        params.put("support_fapiao", true);

        // 金额设置 订单总金额，单位为分，整型。示例：1元应填写 100（微信支付要求）
        BigDecimal amountYuan = order.getTotalAmount();
        log.info("订单金额: {} 元", amountYuan); // 0.01元
//        long totalFee = amountYuan.multiply(new BigDecimal(100)).longValue();

        // 元转分（精确转换）
        long totalFee = amountYuan.multiply(BigDecimal.valueOf(100))
                .setScale(0, BigDecimal.ROUND_HALF_UP)
                .longValue(); // 0.01 * 100 = 1分
        log.info("转换后金额(分): {}", totalFee); // 1分


        Map<String, Object> amount = new HashMap<>();
        amount.put("total", totalFee);
        amount.put("currency", "CNY");
        // 订单金额
        params.put("amount", amount);

        // 支付者信息
        // 获取当前用户ID
        Long userId = SecurityUtils.getUserId();
        // 根据用户ID, 获取当前用户信息
        SysUser user = userService.selectUserById(userId);
        // 获取当前用户微信openid
        String openid = user.getOpenId();

        log.info("用户openid: {}", openid);
        if (StringUtils.isEmpty(openid)) {
            throw new ServiceException("用户未绑定 openid");
        }

        Map<String, Object> payer = new HashMap<>();
        payer.put("openid", openid);
        // 订单支付者信息
        params.put("payer", payer);
        // 优惠功能（选填）

        // 场景信息
//        Map<String, Object> sceneInfo = new HashMap<>();
//        sceneInfo.put("payer_client_ip", user.getLoginIp());
//        params.put("scene_info", sceneInfo);

        // 结算信息（选填） 分销订单就需要分账
//        Map<String, Object> settleInfo = new HashMap<>();
//        settleInfo.put("profit_sharing", true);
//        params.put("settle_info", settleInfo);
//        Map<String, Object> settleInfo = new HashMap<>();
//        // 只有分销订单才需要分账
//        if (order.getDistributorId() != null) {
//            settleInfo.put("profit_sharing", true);
//        } else {
//            settleInfo.put("profit_sharing", false);
//        }
//        params.put("settle_info", settleInfo);


        // 【3】订单参数转为json
        String jsonBody = objectMapper.writeValueAsString(params);

        // 【4】创建请求体
        StringEntity entity = new StringEntity(jsonBody, "utf-8");
        entity.setContentType("application/json");
        httpPost.setEntity(entity);
        httpPost.setHeader("Accept", "application/json");

        // 执行请求
        CloseableHttpResponse response = wxPaymentClient.execute(httpPost);
        // 响应体
        String result = EntityUtils.toString(response.getEntity(), "UTF-8");
        // 响应状态码
        int statusCode = response.getStatusLine().getStatusCode();

        // 【5】执行请求
        try {
            if (statusCode == 200) {
                log.info("请求成功, 返回结果 = " + result);
            } else if (statusCode == 204) {
                log.info("请求成功，无返回结果");
            } else {
                System.out.println("下单失败，响应码 = " + statusCode + "返回结果 = " + result);
                throw new IOException("请求失败");
            }

            // 【6】解析响应结果
            Map<String, String> resultMap = objectMapper.readValue(result, Map.class);

            String prepayId = resultMap.get("prepay_id");
            // 更新支付日志信息
            existingPayLogs.setPrepayId(prepayId);

            payLogsService.updatePayLogs(existingPayLogs);

            // 获取预支付ID后，启动定时任务检查支付状态
            scheduleOrderTimeoutTask(orderId);

            // 6. 返回结果封装
            return buildResponse(order, resultMap);

        } finally {
            response.close();
        }

    }



    // 2. 新增随机字符串生成方法
    private String generateNonceStr(int maxLength) {
        String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < maxLength; i++) {
            sb.append(chars.charAt(random.nextInt(chars.length())));
        }
        return sb.toString();
    }

    // 生成小程序支付签名 (RSA-SHA256)
    private String generatePaySign(String appId, String timeStamp, String nonceStr, String packageValue)
            throws Exception {

        // 1. 严格按照微信格式拼接签名串
        String signData = appId + "\n"
                + timeStamp + "\n"
                + nonceStr + "\n"
                + packageValue + "\n"; // 包含完整"prepay_id=xxx"

        // 2. 获取商户私钥
        PrivateKey privateKey = wxPaymentConfig.getPrivateKey(wxPaymentConfig.getPrivateKeyPath());
        if (privateKey == null) {
            throw new Exception("商户私钥未配置");
        }
        // 3. SHA256withRSA签名
        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initSign(privateKey);
        signature.update(signData.getBytes(StandardCharsets.UTF_8));
        // 4. Base64编码
        return Base64.getEncoder().encodeToString(signature.sign());
    }


    /**
     * 微信支付分账
     *
     * @param orderId 订单ID
     * @return 分账结果
     */
    @Override
    public Map<String, Object> profitSharing(Long orderId) throws Exception {
        log.info("开始处理微信支付分账，订单ID: {}", orderId);

        // 1. 根据订单ID获取订单信息
        Order order = selectOrderByOrderId(orderId);
        if (order == null) {
            throw new ServiceException("订单不存在");
        }

        // 2. 验证订单状态（必须是已支付的订单才能分账）
        if (!"1".equals(order.getMasterStatus())) {
            throw new ServiceException("只有已支付的订单才能进行分账");
        }

        // 3. 获取支付日志，获取微信支付交易号
        PayLogs payLogs = payLogsService.getPayLogsByGoodsOrderId(orderId);
        if (payLogs == null || StringUtils.isEmpty(payLogs.getTransactionId())) {
            throw new ServiceException("未找到支付记录或微信交易号");
        }

        // 4. 获取分销员信息（如果该订单是由分销员下单）
        // 这里需要根据业务逻辑判断是否为分销订单以及获取分销员信息
        // 假设订单表中有一个字段记录了分销员ID
        Long distributorId = order.getDistributorId();
        if (distributorId == null) {
            throw new ServiceException("该订单不是分销订单，无需分账");
        }

        // 5. 根据分销员ID获取分销员信息
        // 这里需要调用分销服务获取分销员信息
        // 由于我们没有分销服务的直接引用，暂时跳过这一步
        // 在实际实现中，需要注入分销服务并获取分销员信息

        // 6. 构造分账请求参数
        Map<String, Object> params = new HashMap<>();
        params.put("appid", wxPaymentConfig.getAppid());
        params.put("transaction_id", payLogs.getTransactionId()); // 微信支付订单号
        params.put("out_order_no", IdUtils.generateOrderCode()); // 商户分账单号

        // 7. 构造分账接收方列表
        List<Map<String, Object>> receivers = new ArrayList<>();

        // 分账给分销员
        Map<String, Object> receiver = new HashMap<>();
        receiver.put("type", "PERSONAL_OPENID"); // 分账接收方类型
        // 这里需要获取分销员的openid，暂时用占位符
        receiver.put("account", "分销员openid"); // 分账接收方账号
        receiver.put("amount", order.getTotalAmount().multiply(BigDecimal.valueOf(100)).intValue()); // 分账金额（分）
        receiver.put("description", "分销佣金"); // 分账描述
        receivers.add(receiver);

        params.put("receivers", receivers);
        params.put("unfreeze_unsplit", true); // 解冻剩余未分资金

        // 8. 发送分账请求到微信支付
        String profitSharingUrl = wxPaymentConfig.getDomain() + "/v3/profitsharing/orders";
        HttpPost httpPost = new HttpPost(profitSharingUrl);

        ObjectMapper objectMapper = new ObjectMapper();
        String jsonBody = objectMapper.writeValueAsString(params);

        StringEntity entity = new StringEntity(jsonBody, "utf-8");
        entity.setContentType("application/json");
        httpPost.setEntity(entity);
        httpPost.setHeader("Accept", "application/json");
        // 添加微信支付公钥序列号头部
        httpPost.setHeader("Wechatpay-Serial", wxPaymentConfig.getMchSerialNo());

        try (CloseableHttpResponse response = wxPaymentClient.execute(httpPost)) {
            int statusCode = response.getStatusLine().getStatusCode();
            String result = EntityUtils.toString(response.getEntity(), "UTF-8");

            Map<String, Object> resultMap = new HashMap<>();
            if (statusCode == 200) {
                resultMap = objectMapper.readValue(result, Map.class);
                resultMap.put("success", true);
                log.info("分账成功，订单ID: {}，结果: {}", orderId, result);
            } else {
                resultMap.put("success", false);
                resultMap.put("errorCode", statusCode);
                resultMap.put("errorMsg", result);
                log.error("分账失败，订单ID: {}，状态码: {}，错误信息: {}", orderId, statusCode, result);
            }

            return resultMap;
        }
    }


    /**
     * 获取微信支付参数
     * @param orderId, oderNo, totalFee, openId
     * @return
     * @throws Exception
     */
    @Override
    public Map<String, String> getWxpayParams(Long orderId, String orderNo, Integer totalFee, String openId) throws Exception {

        // 根据orderId,获取业务订单信息
        Order order = selectOrderByOrderId(orderId);
        if (order == null) {
            throw new ServiceException("订单不存在");
        }
        // 数据库中订单表的金额是元为单位
        BigDecimal amountYuan = order.getTotalAmount(); // 0.01元
        // 数据库中的金额转换成分为单位 * 100
        int amountFen = amountYuan.multiply(BigDecimal.valueOf(100)).intValue(); // 1分
        log.info("前端金额: {}分, 数据库金额: {}分", totalFee, amountFen);

        // 前端传回的金额是以分为单位的
        if (totalFee != amountFen) {
            throw new ServiceException("支付金额与订单金额不一致");
        }

        log.info("获取微信支付参数");
        // 调用JSAPI/小程序下单接口，返回的prepay_id参数值
        HashMap<String, Object> response = miniAppGetPrePayId(orderId);
        // 获取 prepay_id
        String prepayId = (String) response.get("prepayId");

        // 封装参数
        Map<String, String> payParams = new HashMap<>();
        // appId（必填）
        // payParams.put("appid", wxPaymentConfig.getAppid());
        // 当前时间戳（秒，必填）。注意：部分系统取到的值为毫秒级，商户需要转换成秒(10位数字)
        payParams.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000));
        // 随机字符串（必填）
        payParams.put("nonceStr", generateNonceStr(32));
        // 格式固定为"prepay_id=xxx"（必填）
        payParams.put("package", "prepay_id=" + prepayId);
        // 签名类型（与统一下单一致，必填）
        payParams.put("signType", "RSA");

//        // 商品描述（必填）
//        payParams.put("body", "商品描述（如：XX订单支付）");
//        // 客户端IP（可从请求中获取，如request.getRemoteAddr()）
//        payParams.put("spbill_create_ip", IpUtils.getIpAddr());

//        // 支付金额（分，必填）
//        payParams.put("total_fee", String.valueOf(totalFee));
//        // 订单号（唯一，必填）
//        payParams.put("order_no", orderNo);
//        // 用户OpenID（JSAPI必填）
//        payParams.put("openid", openId);

        // 7. 生成RSA签名（严格按照微信规范）
        payParams.put("paySign", generatePaySign(
                wxPaymentConfig.getAppid(),
                payParams.get("timeStamp"),
                payParams.get("nonceStr"),
                payParams.get("package") // 完整package字符串
        ));

        return payParams;
    }


    /**
     * 关闭订单
     * @param orderId
     * @return
     */
    @Override
    public HashMap<String, Object> miniAppCloseOrder(Long orderId) throws Exception {

        // 根据订单ID, 获取当前订单信息
        Order order = selectOrderByOrderId(orderId);
        if (order == null) {
            throw new ServiceException("订单不存在");
        }

        if ("2".equals(order.getMasterStatus())) {
            log.info("订单已关闭，无需重复操作，orderId: {}", orderId);
            HashMap<String, Object> resultMap = new HashMap<>();
            resultMap.put("success", true);
            return resultMap;
        }

        // 如果订单已支付，不应关闭
        if ("1".equals(order.getMasterStatus())) {
            log.info("订单已支付，不能关闭，orderId: {}", orderId);
            HashMap<String, Object> resultMap = new HashMap<>();
            resultMap.put("success", false);
            resultMap.put("reason", "订单已支付");
            return resultMap;
        }

        // 获取已支付的业务订单信息
        PayLogs payLogs = payLogsService.getPayLogsByGoodsOrderId(orderId);

        log.info("获取已支付的业务订单信息，调用关闭订单的接口");
        // 【1】构造带路径参数的URL
        String closeOrderUrl = wxPaymentConfig.getDomain() + WxApiType.CLOSE_ORDER.getType()
                .replace("{out_trade_no}", order.getOrderCode());

        log.info("调用关闭订单API", closeOrderUrl);
        // 创建HTTP请求, 请求https://api.mch.weixin.qq.com//v3/pay/transactions/out-trade-no/{out_trade_no}/close 关闭订单接口
        HttpPost httpPost = new HttpPost(closeOrderUrl);

        // 【2】封装关闭订单请求的Body参数
        log.info("封装关闭订单请求的Body参数");
        // 创建JSON对象
        ObjectMapper objectMapper = new ObjectMapper();
        // 创建表单对象
        Map<Object, Object> params = new HashMap<>();

        // 微信小程序关闭订单请求, Body参数:
        // 商户号
        params.put("mchid", wxPaymentConfig.getMchId());

        // 【3】订单参数转为json
        String jsonBody = objectMapper.writeValueAsString(params);

        // 【4】创建请求体
        StringEntity entity = new StringEntity(jsonBody, "utf-8");
        entity.setContentType("application/json");
        httpPost.setEntity(entity);
        httpPost.setHeader("Accept", "application/json");

        try (CloseableHttpResponse response = wxPaymentClient.execute(httpPost)) {
            int statusCode = response.getStatusLine().getStatusCode();
            String result = "";

            // 仅当响应体存在时解析内容
            HttpEntity responseEntity = response.getEntity();
            if (responseEntity != null) {
                result = EntityUtils.toString(responseEntity, "UTF-8");
            } else {
                log.warn("关闭订单API返回空响应体，订单ID: {}, 状态码: {}", orderId, statusCode);
            }

            // 【5】处理响应结果
            HashMap<String, Object> resultMap = new HashMap<>();
            resultMap.put("success", false);

            if (statusCode == 204) {
                log.info("订单关闭成功，订单ID: {}", orderId);
                resultMap.put("success", true);

                // 更新订单状态为关闭
                order.setMasterStatus("2"); // 订单关闭
                int rows = updateOrder(order);
                if (rows <= 0) {
                    log.error("订单关闭状态更新失败，订单ID: {}", orderId);
                }

                // 更新订单支付日志信息
                if (payLogs != null) {
                    payLogs.setPaymentStatus("2"); // 支付失败
                    int logRows = payLogsService.updatePayLogs(payLogs);
                    if (logRows <= 0) {
                        log.error("订单支付日志状态更新失败，订单ID: {}", orderId);
                    }
                }
            } else {
                log.error("关闭订单失败，订单ID: {}, 状态码: {}, 响应: {}", orderId, statusCode, result);
                resultMap.put("errorCode", statusCode);
                resultMap.put("errorMsg", result);
            }

            return resultMap;
        }
    }


    /**
     * 用户申请退款
     * 事务说明：
     * 1. 创建新的退款申请记录
     * 2. 更新订单状态
     * 3. 以上操作必须原子执行，任一失败则回滚
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void applyRefund(RefundApplyDto refundApplyDto) {
        // 1. 验证订单是否存在
        Order order = selectOrderByOrderId(refundApplyDto.getOrderId());
        if (order == null) {
            throw new ServiceException("订单不存在");
        }

        // 2. 检查分销配置中的退款功能开关
        DistributionConfig config = distributionConfigService.selectDistributionConfigByConfigId(1L);
        if (config != null && "0".equals(config.getRefundSwitch())) {
            throw new ServiceException("系统当前关闭了订单退款功能，无法申请退款");
        }

        // 3. 验证订单状态（已支付才能申请退款）
        if (!"1".equals(order.getMasterStatus())) {
            throw new ServiceException("只有已支付订单才能申请退款");
        }

        // 3. 检查是否有"处理中"的退款申请（关键修改）
        List<RefundInfo> activeRefunds = refundInfoService.selectActiveRefundsByGoodsOrderId(refundApplyDto.getOrderId());
        if (!activeRefunds.isEmpty()) {
            throw new ServiceException("该订单已有处理中的退款申请");
        }

        // 4. 验证订单的支付记录是否存在
        PayLogs payLogs = payLogsService.getPayLogsByGoodsOrderId(refundApplyDto.getOrderId());
        if (payLogs == null) {
            throw new ServiceException("支付记录不存在");
        }

        // 5. 创建新的退款申请记录
        RefundInfo refundInfo = new RefundInfo();
        // 商品订单ID
        refundInfo.setGoodsOrderId(refundApplyDto.getOrderId());
        refundInfo.setPaymentId(payLogs.getPaymentId());
        log.info("创建新的退款申请");

        // 6. 设置退款金额（默认为订单金额）
        BigDecimal refundAmount = refundApplyDto.getAmount() != null ?
                refundApplyDto.getAmount() : order.getTotalAmount();
        if (refundAmount.compareTo(payLogs.getAmount()) > 0) {
            throw new ServiceException("退款金额不能超过支付金额");
        }
        refundInfo.setRefundAmt(refundAmount);

        // 7. 设置退款原因
        refundInfo.setReason(refundApplyDto.getReason());
        // 8. 设置审核状态为"待审核"
        refundInfo.setRefundAuditStatus("0");
        // 9. 设置退款状态为"申请中"
        refundInfo.setRefundStatus("1");
        // 10. 生成退款单号
        refundInfo.setRefundCode(IdUtils.generateRefundCode());

        // 11. 保存退款申请
        refundInfoService.insertRefundInfo(refundInfo);
        log.info("成功创建退款申请，退款ID: {}", refundInfo.getRefundId());

        // 12. 更新订单状态为"退款申请中"
        // 如果订单当前状态不是"已支付"，则可能已经有退款申请在处理
        if (!"1".equals(order.getMasterStatus())) {
            log.warn("订单状态异常，当前状态: {}", order.getMasterStatus());
        }

        // 如果已有退款申请，状态可能已经是"3"（退款中）
        if (!"3".equals(order.getMasterStatus())) {
            order.setMasterStatus("3");
            orderMapper.updateOrder(order);
            log.info("成功更新订单状态为退款申请中，订单ID: {}", order.getOrderId());
        }
    }

    /**
     * 退款审核
     * 参数：审核结果、审核理由
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void auditRefundApplication(Long refundId, RefundAuditDto auditDto) throws Exception {
        // 1. 检查分销配置中的退款功能开关
        DistributionConfig config = distributionConfigService.selectDistributionConfigByConfigId(1L);
        if (config != null && "0".equals(config.getRefundSwitch())) {
            throw new ServiceException("系统当前关闭了订单退款功能，无法进行退款审核");
        }

        // 2. 获取退款申请
        RefundInfo refundInfo = refundInfoService.selectRefundInfoByRefundId(refundId);
        if (refundInfo == null) {
            throw new ServiceException("退款申请不存在");
        }

        // 获取订单
        Order order = orderService.selectOrderByOrderId(refundInfo.getGoodsOrderId());
        if (order == null) {
            throw new ServiceException("订单不存在");
        }
        // 获取订单
//        Long orderId = refundInfo.getGoodsOrderId();
//        Order order = selectOrderByOrderId(orderId);


        // 2. 验证退款申请状态（必须是待审核）
        if (!"0".equals(refundInfo.getRefundAuditStatus())) {
            throw new ServiceException("退款申请状态异常，无法审核");
        }

        // 3. 更新退款申请审核信息
        refundInfo.setRefundAuditStatus(auditDto.getAuditStatus());
        refundInfo.setAuditRemark(auditDto.getAuditReason());
        refundInfo.setAuditTime(new Date());
        refundInfo.setAuditBy(SecurityUtils.getUsername());

        // 4. 处理审核结果
        if ("1".equals(auditDto.getAuditStatus())) { // 审核通过
            // 先更新退款状态为"2=退款中"
            refundInfo.setRefundStatus("2");
            refundInfo.setRefundAuditStatus("1");
            refundInfoService.updateRefundInfo(refundInfo);
            try {
                // 执行微信退款（同步操作）
                HashMap<String, Object> refundResult = miniAppRefund(refundInfo.getGoodsOrderId(), refundInfo.getReason());
                // 执行微信退款（同步操作）
                // 验证退款结果
                if (refundResult != null && (Boolean) refundResult.get("success")) {
                    String refundTransId = (String) refundResult.get("refundTransId");
                    // 1. 更新退款记录状态
                    refundInfo.setRefundStatus("3"); // 已退款
                    refundInfo.setRefundTransId(refundTransId);
                    refundInfo.setRefundTime(new Date());
                    refundInfoService.updateRefundInfo(refundInfo);
                    log.info("更新退款状态为：已退款，微信退款单号：{}", refundTransId);

                    // 2. 更新订单状态
                    order.setMasterStatus("4"); // 已退款
                    updateOrder(order);
                    log.info("更新订单状态为：已退款，订单ID：{}", order.getOrderId());

                    // 3. 更新支付日志
                    PayLogs payLogs = payLogsService.getPayLogsByGoodsOrderId(refundInfo.getGoodsOrderId());
                    if (payLogs != null) {
                        payLogs.setRefundAmount(refundInfo.getRefundAmt());
                        payLogs.setRefundStatus("3"); // 已退款
                        payLogs.setRefundTime(new Date());
                        payLogsService.updatePayLogs(payLogs);
                        log.info("更新支付日志中的退款相关数据");
                    }

                    // 4. 更新订单分销关联中的分销状态
                    DistributionOrderRelation relationOrder = distributionOrderRelationService.selectDistributionOrderRelationByOrderId(order.getOrderId());
                    if (relationOrder != null) {
                        // 更新分销订单状态为已退款 分销状态：0-待支付 1-待结算 2-已结算 3-已取消 4-已扣回
                        relationOrder.setDistributionStatus("3"); // 已退款
                        relationOrder.setCancelReason("已微信退款，退款原因:" + refundInfo.getReason());
                        distributionOrderRelationService.updateDistributionOrderRelation(relationOrder);
                        log.info("更新分销订单状态为已退款，分销订单ID：{}", relationOrder.getRelationId());

                        // 在退款成功后，处理返佣取消
                        handleCommissionRefund(order.getOrderId());
                    }
                    // ===== 更新结束 =====
                } else {
                    throw new ServiceException("微信退款返回异常结果");
                }
            } catch (Exception e) {
                // 退款失败，回滚状态
                refundInfo.setRefundStatus("4"); // 退款失败
                refundInfoService.updateRefundInfo(refundInfo);
                throw e;
            }
        } else if ("2".equals(auditDto.getAuditStatus())) { // 审核拒绝
            // 更新退款审核状态为"审核驳回"
            refundInfo.setRefundAuditStatus("2");
            refundInfo.setAuditRemark(auditDto.getAuditReason());
            refundInfo.setAuditTime(new Date());
            refundInfo.setAuditBy(SecurityUtils.getUsername());

            refundInfoService.updateRefundInfo(refundInfo);

            // 检查是否还有其他处理中的退款申请
            List<RefundInfo> processingRefunds = refundInfoService.selectActiveRefundsByGoodsOrderId(refundInfo.getGoodsOrderId());
            if (processingRefunds.isEmpty()) {
                // 没有其他有效退款申请，恢复订单状态
                order.setMasterStatus("1"); // 已支付
                updateOrder(order);
                log.info("订单状态已恢复为已支付，订单ID: {}", order.getOrderId());
            } else {
                log.info("订单ID: {} 仍有 {} 个处理中的退款申请，不恢复订单状态",
                        order.getOrderId(), processingRefunds.size());
            }

        }

        // 5. 保存退款审核记录
        refundInfoService.updateRefundInfo(refundInfo);
    }

    /**
     * 微信退款
     *
     * @param orderId
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public HashMap<String, Object> miniAppRefund(Long orderId, String reason) throws Exception {

        // 根据订单ID, 获取当前订单信息
        Order order = selectOrderByOrderId(orderId);
        if (order == null) {
            throw new ServiceException("订单不存在");
        }
        // 订单在数据库中的金额
        BigDecimal amountYuan = order.getTotalAmount(); // 0.01元
        // 数据库中的金额转换成分
        int amountFen = amountYuan.multiply(BigDecimal.valueOf(100)).intValue(); // 1分
        log.info("转换后的金额: {}分", amountFen); // 1分

        // 获取已支付的业务订单信息
        PayLogs payLogs = payLogsService.getPayLogsByGoodsOrderId(orderId);
        if (payLogs == null) {
            throw new ServiceException("未找到支付记录");
        }

        // 3. 获取当前退款申请（最新创建的待处理退款）
        RefundInfo refundInfo = refundInfoService.getLatestRefundByGoodsOrderId(orderId);
        if (refundInfo == null) {
            throw new ServiceException("未找到退款申请");
        }

        // 4. 验证退款申请状态
        if (!"1".equals(refundInfo.getRefundAuditStatus()) || !"2".equals(refundInfo.getRefundStatus())) {
            throw new ServiceException("退款申请状态异常，无法执行退款");
        }

        // 2. 查询现有退款记录
//        RefundInfo existingRefundInfo = refundInfoService.selectByOrderId(orderId);
        String refundNo = IdUtils.generateRefundCode(); // 退款编号
//        RefundInfo refundInfo;

        log.info("开始处理微信退款请求");
        // 退款回调地址
        String notifyUrl = wxPaymentConfig.getNotifyDomain() + "/wxpay/refund";

        // 微信小程序申请退款请求Body参数:
        log.info("封装退款请求的Body参数");
        // 创建表单对象
        Map<Object, Object> params = new HashMap<>();
        // 商户订单号【transaction_id和out_trade_no必须二选一进行传参。】
        params.put("out_trade_no", order.getOrderCode());
        // 商户退款单号
        params.put("out_refund_no", refundNo);
        // 退款原因（选填）
        params.put("reason", reason);
        // 退款结果回调地址(选填)
        params.put("notify_url", notifyUrl);
        // 退款资金来源
        // 退款金额 【退款金额，币种的最小单位，只能为整数，不能超过原订单支付金额】
        // 金额设置 订单总金额，单位为分，整型。示例：1元应填写 100
        // BigDecimal amountYuan = order.getAmount();
        // log.info("订单金额: {} 元", amountYuan);
        long refundFee = amountYuan.multiply(new BigDecimal(100)).longValue();
        log.info("转换后金额(元): {}", refundFee);

        // 退款金额和原订单金额设计为一致
        Map<String, Object> amountMap = new HashMap<>();
        amountMap.put("refund", refundFee); // 退款金额，单位为分
        amountMap.put("total", refundFee);  // 订单金额，单位为分
        amountMap.put("currency", "CNY");   // 币种，CNY：人民币
        params.put("amount", amountMap);
        // 退款商品(选填）

        // 创建JSON对象
        ObjectMapper objectMapper = new ObjectMapper();
        // 订单参数转为json
        String jsonBody = objectMapper.writeValueAsString(params);

        // 构造退款API的URL
        log.info("调用申请退款订单API");
        String refundOrderUrl = wxPaymentConfig.getDomain() + WxApiType.REFUND.getType();
        // 创建HTTP请求, 请求https://api.mch.weixin.qq.com/v3/refund/domestic/refunds 申请退款接口
        HttpPost httpPost = new HttpPost(refundOrderUrl);

        // 创建请求对象
        StringEntity entity = new StringEntity(jsonBody, "utf-8");
        entity.setContentType("application/json");  // 设置请求内容类型为JSON
        httpPost.setEntity(entity);  // 设置请求体
        httpPost.setHeader("Accept", "application/json"); // 设置响应内容类型为JSON

        // 发送请求并获取响应
        try (CloseableHttpResponse response = wxPaymentClient.execute(httpPost)) {
            int statusCode = response.getStatusLine().getStatusCode();
            // 返回的应答参数
            String result = EntityUtils.toString(response.getEntity(), "UTF-8");

            // 在微信退款API调用成功后添加以下代码
            if (statusCode == 200) {
                // 1. 解析微信返回的退款结果
                // Map<String, Object> resultMap = objectMapper.readValue(result, new TypeReference<Map<String, Object>>() {});
                Map<String, String> resultMap = objectMapper.readValue(result, Map.class);
                String refundTransId = (String) resultMap.get("refund_id");

                // 返回成功结果
                HashMap<String, Object> map = new HashMap<>();
                map.put("success", true);
                map.put("refundId", refundTransId);
                return map;
            } else {
                // 退款失败处理
                refundInfo.setRefundStatus("4"); // 退款失败
                refundInfoService.updateRefundInfo(refundInfo);
                log.error("微信退款失败，订单ID：{}，状态码：{}", orderId, statusCode);
                throw new ServiceException("微信退款失败，状态码：" + statusCode);
            }

        } catch (Exception e) {
            log.error("微信退款接口调用异常，订单ID: {}", orderId, e);
            throw new ServiceException("微信退款处理异常: " + e.getMessage());
        }
    }


    /**
     * 处理订单退款时的返佣取消
     * @param orderId 订单ID
     */
    private void handleCommissionRefund(Long orderId) {
        try {
            log.info("开始处理订单退款返佣取消，订单ID: {}", orderId);

            // 1. 查询该订单的分销关联记录
            DistributionOrderRelation relation = distributionOrderRelationService.selectDistributionOrderRelationByOrderId(orderId);
            if (relation == null) {
                log.info("订单 {} 无分销关联记录，无需处理返佣取消", orderId);
                return;
            }

            // 2. 检查分销状态，如果不是已结算或待结算状态，则无需处理
            String distributionStatus = relation.getDistributionStatus();
            if ("3".equals(distributionStatus) || "4".equals(distributionStatus)) {
                log.info("订单 {} 分销状态为已取消或已扣回，无需重复处理", orderId);
                return;
            }

            // 3. 更新分销订单关联状态为"已取消"
            relation.setDistributionStatus("3"); // 3-已取消
            relation.setCancelReason("订单退款");
            relation.setUpdateTime(new Date());
            distributionOrderRelationService.updateDistributionOrderRelation(relation);
            log.info("更新订单 {} 分销关联记录状态为已取消", orderId);

            // 4. 扣回钱包中的相关金额
            handleWalletDeduction(relation);

        } catch (Exception e) {
            log.error("处理订单退款返佣取消时发生异常，订单ID: {}", orderId, e);
            // 不抛出异常，避免影响主流程
        }
    }

    /**
     * 扣回钱包中的相关金额
     * @param relation 分销订单关联记录
     */
    private void handleWalletDeduction(DistributionOrderRelation relation) {
        try {
            // 处理一级分销员
            if (relation.getFirstDistributorId() != null) {
                deductWalletAmount(relation.getFirstDistributorId(), relation.getOrderId(), "1");
            }

            // 处理二级分销员
            if (relation.getSecondDistributorId() != null) {
                deductWalletAmount(relation.getSecondDistributorId(), relation.getOrderId(), "2");
            }
        } catch (Exception e) {
            log.error("扣回钱包金额时发生异常，关联ID: {}", relation.getRelationId(), e);
        }
    }

    /**
     * 扣回指定分销员的钱包金额
     * @param distributorId 分销员ID
     * @param orderId 订单ID
     * @param level 分销层级
     */
    private void deductWalletAmount(Long distributorId, Long orderId, String level) {
        try {
            // 1. 查询该分销员的钱包
            DistributionWallet wallet = distributionWalletService.selectWalletByDistributorId(distributorId);
            if (wallet == null) {
                log.warn("分销员 {} 未找到钱包信息", distributorId);
                return;
            }

            // 2. 查询该订单该分销员的返佣收入记录
            DistributionIncome income = distributionIncomeService.selectIncomeByOrderIdAndDistributorId(orderId, distributorId);
            if (income == null) {
                log.warn("未找到订单 {} 分销员 {} 的返佣收入记录", orderId, distributorId);
                return;
            }

            BigDecimal rebateAmount = income.getRebateAmount();
            if (rebateAmount == null || rebateAmount.compareTo(BigDecimal.ZERO) <= 0) {
                log.info("分销员 {} 返佣金额为0或负数，无需扣回", distributorId);
                return;
            }

            // 3. 根据分销状态判断从哪个余额中扣回
            String distributionStatus = income.getIncomeStatus();
            if ("1".equals(distributionStatus)) { // 待结算状态
                // 从待结算余额中扣回
                BigDecimal pendingBalance = wallet.getPendingSettlementBalance();
                if (pendingBalance != null) {
                    wallet.setPendingSettlementBalance(
                        pendingBalance.subtract(rebateAmount).compareTo(BigDecimal.ZERO) < 0 ?
                        BigDecimal.ZERO :
                        pendingBalance.subtract(rebateAmount)
                    );
                }
            } else if ("2".equals(distributionStatus)) { // 已结算/可用状态
                // 从可用余额中扣回
                BigDecimal availableBalance = wallet.getAvailableBalance();
                if (availableBalance != null) {
                    wallet.setAvailableBalance(
                        availableBalance.subtract(rebateAmount).compareTo(BigDecimal.ZERO) < 0 ?
                        BigDecimal.ZERO :
                        availableBalance.subtract(rebateAmount)
                    );
                }
            }

            // 4. 更新钱包
            wallet.setUpdateTime(new Date());
            wallet.setUpdateBy("system-refund");
            distributionWalletService.updateDistributionWallet(wallet);

            // 5. 更新返佣收入记录状态为"已扣回"
            income.setIncomeStatus("4"); // 4-已扣回
            income.setUpdateTime(new Date());
            income.setUpdateBy("system-refund");
            distributionIncomeService.updateDistributionIncome(income);

            log.info("成功扣回分销员 {} 的返佣金额 {} 元，订单ID: {}", distributorId, rebateAmount, orderId);
        } catch (Exception e) {
            log.error("扣回分销员 {} 钱包金额时发生异常，订单ID: {}", distributorId, orderId, e);
        }
    }



    /**
     * 根据顾客id和商品订单状态获取交易订单列表
     */
    @Override
    public List<Order> selectOrderByGuestIdAndOrderStatus(Long guestId, String orderStatus) {
        Order orderQuery = new Order();
        orderQuery.setGuestId(guestId);

        // 当orderStatus不为null时添加支付状态条件
        if (orderStatus != null) {
            orderQuery.setMasterStatus(orderStatus);
        }

        return orderMapper.selectOrderByGuestIdAndOrderStatus(orderQuery);
    }

    /**
     * 根据顾客id和商品订单状态获取交易订单列表（分页）
     */
    @Override
    public List<Order> selectOrderByGuestIdAndOrderStatusWithPagination(Long guestId, String masterStatus, int pageNum, int pageSize) {
        Order orderQuery = new Order();
        orderQuery.setGuestId(guestId);

        // 当masterStatus不为null时添加支付状态条件
        if (masterStatus != null) {
            orderQuery.setMasterStatus(masterStatus);
        }

        // 使用传统的分页方式，通过LIMIT和OFFSET实现
        // 注意：Mapper接口参数名为orderStatus，但Service层参数名为masterStatus，需要保持一致
        return orderMapper.selectOrderByGuestIdAndOrderStatusWithPagination(guestId, masterStatus, (pageNum - 1) * pageSize, pageSize);
    }

    /**
     * 统计顾客id和商品订单状态下的订单数量
     */
    @Override
    public int countOrderByGuestIdAndOrderStatus(Long guestId, String masterStatus) {
        Order orderQuery = new Order();
        orderQuery.setGuestId(guestId);

        // 当masterStatus不为null时添加支付状态条件
        if (masterStatus != null) {
            orderQuery.setMasterStatus(masterStatus);
        }

        return orderMapper.countOrderByGuestIdAndOrderStatus(guestId, masterStatus);
    }



    /**
     * 根据订单ID查询订单信息，并关联查询商品详情
     */
    @Override
    public Order selectOrderByOrderIdWithDetails(Long orderId) {
        // 1. 查询主订单
        Order order = selectOrderByOrderId(orderId);
        if (order == null) {
            return null;
        }

        // 2. 查询商品详情
        OrderGoodsDetail goodsDetails = orderGoodsDetailService.selectOrderGoodsDetailByOrderId(orderId);
        order.setGoodsDetails(goodsDetails);

        return order;
    }

    /**
     * 查询订单列表
     */
    @Override
    public List<Order> selectOrderSummaryList(Order order) {
        return orderMapper.selectoOrderSummaryList(order);
    }

    /**
     * 根据订单号获取订单信息
     */
    @Override
    public Order getByOrderCode(String orderCode) {
        if (StringUtils.isEmpty(orderCode)) {
            throw new ServiceException("订单号不能为空");
        }
        return orderMapper.selectOrderByOrderCode(orderCode);
    }

    /**
     * 匹配返佣规则
     *
     * @param order 订单信息
     * @param distributor 上级分销员
     * @param relationLevel 关系层级
     * @return 匹配的返佣规则，如果没有匹配的规则则返回null
     */
    @Override
    public RebateRule matchRebateRule(Order order, DistributionUser distributor, String relationLevel) {
        try {
            log.info("开始匹配返佣规则，订单ID: {}, 分销员ID: {}, 关系层级: {}",
                    order.getOrderId(), distributor.getDistributorId(), relationLevel);

            // 根据订单类型确定商品类型
            String productType = determineProductType(order);

            // 创建查询条件
            RebateRule queryRule = new RebateRule();

            // 1. 商品类型：根据订单内容动态确定
            queryRule.setProductType(productType);

            // 2. 等级匹配：grade_id=上级分销员的grade_id
            queryRule.setGradeId(distributor.getGradeId());

            // 3. 层级匹配：relation_level=上级的relation_level
            queryRule.setRelationLevel(relationLevel);

            // 4. 规则状态：status=0（正常）
            queryRule.setStatus("0");

            // 查询符合条件的规则
            List<RebateRule> rules = rebateRuleService.selectRebateRuleList(queryRule);

            if (rules == null || rules.isEmpty()) {
                log.info("未找到符合条件的返佣规则");
                return null;
            }

            // 过滤规则生效时间及金额门槛
            Date now = new Date();
            List<RebateRule> matchedRules = rules.stream()
                    .filter(rule ->
                            // 规则生效时间检查
                            (rule.getValidTimeStart() == null || !rule.getValidTimeStart().after(now)) &&
                                    (rule.getValidTimeEnd() == null || !rule.getValidTimeEnd().before(now)) &&
                                    // 金额门槛检查
                                    (rule.getMinOrderAmount() == null ||
                                            order.getTotalAmount().compareTo(rule.getMinOrderAmount()) >= 0)
                    )
                    .collect(Collectors.toList());

            if (matchedRules.isEmpty()) {
                log.info("未找到在有效期内且满足金额门槛的返佣规则");
                return null;
            }

            // 如果有多个匹配规则，选择创建时间最新的规则
            RebateRule matchedRule = matchedRules.stream()
                    .max(Comparator.comparing(RebateRule::getCreateTime))
                    .orElse(null);

            log.info("成功匹配到返佣规则，规则ID: {}", matchedRule != null ? matchedRule.getRuleId() : null);
            return matchedRule;
        } catch (Exception e) {
            log.error("匹配返佣规则时发生异常，订单ID: {}", order.getOrderId(), e);
            return null;
        }
    }

    /**
     * 根据订单信息确定商品类型
     *
     * @param order 订单信息
     * @return 商品类型编码 (1-自助餐券 2-节日礼盒 3-住宿套餐)
     */
    private String determineProductType(Order order) {
        // 这里需要根据订单的具体内容来判断商品类型
        // 示例实现，实际需要根据业务逻辑调整
        if (order.getOrderType() != null) {
            switch (order.getOrderType()) {
                case "1": // 假设1代表自助餐券订单
                    return "1";
                case "2": // 假设2代表住宿套餐订单
                    return "2";
                case "3": // 假设3代表节日礼盒订单
                    return "3";
                default:
                    return "1"; // 默认为自助餐券
            }
        }
        return "1"; // 默认为自助餐券
    }


    /**
     * 查询订单支付状态
     *
     * @param orderNo 订单号
     * @return 订单支付状态
     */
    @Override
    public String checkOrderPaymentStatus(String orderNo) {
        // 1. 根据订单号查询订单
        Order order = orderMapper.selectOrderByOrderCode(orderNo);
        if (order == null) {
            throw new ServiceException("订单不存在");
        }

        // 2. 返回订单支付状态
        return order.getMasterStatus();
    }


    /**
     * 根据核销码查询订单
     * @param verificationCode 核销码
     * @return 订单信息
     */
    @Override
    public Order selectOrderByVerificationCode(String verificationCode) {
        return orderMapper.selectOrderByVerificationCode(verificationCode);
    }

    /**
     * 核销订单
     * @param verificationCode 核销码
     * @return 核销结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean verifyOrderWithAuth(String verificationCode) {
        // 1. 根据核销码查询订单
        Order order = selectOrderByVerificationCode(verificationCode);
        if (order == null) {
            throw new ServiceException("未找到对应的订单");
        }

        // 2. 检查订单状态
        if (!"1".equals(order.getMasterStatus())) {
            throw new ServiceException("订单状态异常，无法核销");
        }

        // 3. 检查核销状态
        if (!"0".equals(order.getVerificationStatus())) {
            throw new ServiceException("订单已核销或状态异常");
        }

        // 4. 更新核销状态
        order.setVerificationStatus("1"); // 已使用
        order.setVerificationTime(new Date()); // 核销时间
        order.setUpdateTime(new Date());

        int result = orderMapper.updateOrder(order);
        if (result <= 0) {
            throw new ServiceException("核销失败");
        }

        // 5. 创建核销码明细信息
        try {
            createVerificationDetail(order, verificationCode);
        } catch (Exception e) {
            log.error("创建核销码明细信息失败，订单ID: {}", order.getOrderId(), e);
            // 这里可以选择是否回滚订单状态更新，根据业务需求决定
        }

        log.info("订单核销成功，订单ID: {}，核销码: {}", order.getOrderId(), verificationCode);
        return true;
    }

    /**
     * 创建核销码明细信息
     * @param order 订单信息
     * @param verificationCode 核销码
     */
    private void createVerificationDetail(Order order, String verificationCode) {
        try {
            // 创建核销码明细信息
            VerificationDetail verificationDetail = new VerificationDetail();

            // 设置核销码明细信息
            verificationDetail.setOrderId(order.getOrderId());
            verificationDetail.setOrderCode(order.getOrderCode());

            // 从订单详情中获取商品信息
            OrderGoodsDetail orderGoodsDetail = orderGoodsDetailService.selectOrderGoodsDetailByOrderId(order.getOrderId());
            if (orderGoodsDetail != null) {
                verificationDetail.setGoodsId(orderGoodsDetail.getGoodsId());

                // 处理SKU信息 - 如果没有规格信息，则使用默认值
                if (orderGoodsDetail.getSkuId() != null) {
                    verificationDetail.setSkuId(orderGoodsDetail.getSkuId());
                } else {
                    // 如果没有skuId，设置默认值0
                    verificationDetail.setSkuId(0L);
                }

                // 如果有规格名称就使用，否则使用默认值
                if (StringUtils.isNotEmpty(orderGoodsDetail.getSpecs())) {
                    verificationDetail.setSkuName(orderGoodsDetail.getSpecs());
                } else {
                    verificationDetail.setSkuName("默认规格");
                }
            } else {
                // 如果没有订单详情，设置默认值
                verificationDetail.setSkuId(0L);
                verificationDetail.setSkuName("默认规格");
            }

            verificationDetail.setVerificationCode(verificationCode);

            // 生成核销码哈希值用于防篡改
            verificationDetail.setVerificationHash(generateVerificationHash(verificationCode));

            // 设置使用状态为已使用
            verificationDetail.setUseStatus("1");

            // 设置核销时间
            verificationDetail.setUseTime(new Date());

            // 设置核销操作人（如果可以获得当前操作人信息）
            // verificationDetail.setUseBy(SecurityUtils.getUsername());

            // 设置赠送状态为未赠送
            verificationDetail.setGiftedStatus("0");

            // 设置有效期（根据业务需求设置）
            // 设置默认有效期为一年
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(new Date());
            calendar.add(Calendar.YEAR, 1);
            verificationDetail.setValidEndTime(calendar.getTime());

            // 设置删除标志
            verificationDetail.setDelFlag("0");

            // 设置版本号
            verificationDetail.setVersion(1L);

            // 设置创建信息
            verificationDetail.setCreateTime(new Date());
            // verificationDetail.setCreateBy(SecurityUtils.getUsername());

            // 保存核销码明细信息
            verificationDetailService.insertVerificationDetail(verificationDetail);

            log.info("核销码明细信息创建成功，订单ID: {}，核销码: {}", order.getOrderId(), verificationCode);
        } catch (Exception e) {
            log.error("创建核销码明细信息异常，订单ID: {}", order.getOrderId(), e);
            throw new ServiceException("创建核销码明细信息失败: " + e.getMessage());
        }
    }



    /**
     * 生成核销码哈希值
     * @param verificationCode 核销码
     * @return 哈希值
     */
    private String generateVerificationHash(String verificationCode) {
        // 简单实现，可以使用MD5、SHA等算法
        return String.valueOf(verificationCode.hashCode());
    }



    /**
     * 根据订单ID获取核销信息
     *
     * @param orderId 订单ID
     * @return 核销信息
     */
    @Override
    public Map<String, Object> getOrderVerificationInfo(Long orderId) {
        Order order = selectOrderByOrderId(orderId);
        if (order == null) {
            throw new ServiceException("订单不存在");
        }

        Map<String, Object> result = new HashMap<>();
        result.put("orderId", order.getOrderId());
        result.put("orderCode", order.getOrderCode());
        result.put("verificationCode", order.getVerificationCode());
        result.put("verificationStatus", order.getVerificationStatus());
        result.put("verificationTime", order.getVerificationTime());
        result.put("goodsDetails", order.getGoodsDetails());

        return result;
    }

    /**
     * 重新生成核销码
     *
     * @param orderId 订单ID
     * @return 新的核销码
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String regenerateVerificationCode(Long orderId) {
        Order order = selectOrderByOrderId(orderId);
        if (order == null) {
            throw new ServiceException("订单不存在");
        }

        // 检查订单状态，只有已支付且未核销的订单可以重新生成核销码
        if (!"1".equals(order.getMasterStatus())) {
            throw new ServiceException("只有已支付的订单才能重新生成核销码");
        }

        if ("1".equals(order.getVerificationStatus())) {
            throw new ServiceException("订单已核销，无法重新生成核销码");
        }

        // 生成新的核销码
        String newVerificationCode = generateVerificationCode();

        // 更新订单的核销码
        order.setVerificationCode(newVerificationCode);
        order.setUpdateTime(new Date());
        int result = orderMapper.updateOrder(order);

        if (result <= 0) {
            throw new ServiceException("重新生成核销码失败");
        }

        log.info("订单重新生成核销码成功，订单ID: {}，新核销码: {}", orderId, newVerificationCode);
        return newVerificationCode;
    }

    /**
     * 生成核销码
     * @return 核销码
     */
    private String generateVerificationCode() {
        // 生成唯一的核销码，可以使用UUID或者其他算法
        return "VC" + System.currentTimeMillis() + (int)(Math.random() * 10000);
    }

    /**
     * 检查缓存中的分销关系并设置到订单中（如果存在）
     *
     * @param order 订单对象
     * @param userId 用户ID
     * @param orderItems 订单商品项列表
     */
    private void setCachedDistributorIfExists(Order order, Long userId, List<OrderItemDTO> orderItems) {
        try {
            // 检查用户是否有缓存的分销关系
            if (distributionRelationCacheService.hasTemporaryRelation(userId)) {
                // 获取缓存的分销关系
                Map<String, Object> cachedRelation = distributionRelationCacheService.getTemporaryRelation(userId);
                if (cachedRelation != null) {
                    Long distributorId = (Long) cachedRelation.get("distributorId");
                    Long cachedGoodsId = (Long) cachedRelation.get("goodsId");

                    // 验证缓存的分销关系和当前订单商品是否匹配
                    if (distributorId != null && isGoodsIdInOrderItems(cachedGoodsId, orderItems)) {
                        // 验证分销员状态是否有效
                        DistributionUser distributor = distributionUserService.selectDistributionUserByDistributorId(distributorId);
                        if (distributor != null && "0".equals(distributor.getStatus())
                                && "0".equals(distributor.getDelFlag())
                                && "1".equals(distributor.getAuthStatus())) {

                            // 设置缓存的分销员ID到订单中
                            order.setDistributorId(distributorId);
                            log.info("订单关联缓存分销员ID: {}", distributorId);

                            // 成功后删除缓存，避免重复使用
                            distributionRelationCacheService.removeTemporaryRelation(userId);
                            return;
                        } else {
                            log.warn("缓存的分销员ID无效或状态异常: {}", distributorId);
                            // 删除无效的缓存
                            distributionRelationCacheService.removeTemporaryRelation(userId);
                        }
                    } else {
                        log.info("缓存的分销关系与当前订单商品不匹配，商品ID: {}", cachedGoodsId);
                    }
                }
            }

            // 如果缓存中没有有效分销关系，则查询上级分销员
            setParentDistributorIfExists(order, userId);

        } catch (Exception e) {
            log.warn("检查缓存分销关系时发生异常: {}", e.getMessage());
            // 即使检查失败，也不影响订单创建流程，继续查询上级分销员
            setParentDistributorIfExists(order, userId);
        }
    }

    /**
     * 检查是否包含指定商品ID的商品项
     *
     * @param goodsId 商品ID
     * @param orderItems 订单商品项列表
     * @return 是否包含
     */
    private boolean isGoodsIdInOrderItems(Long goodsId, List<OrderItemDTO> orderItems) {
        if (goodsId == null || orderItems == null || orderItems.isEmpty()) {
            return false;
        }

        return orderItems.stream()
                .anyMatch(item -> goodsId.equals(item.getGoodsId()));
    }

    /**
     * 设置用户的上级分销员到订单中（如果存在）
     *
     * @param order 订单对象
     * @param userId 用户ID
     */
    private void setParentDistributorIfExists(Order order, Long userId) {
        try {
            // 查询用户的上级分销员信息
            DistributionUser parentDistributor = getParentDistributor(userId);
            if (parentDistributor != null) {
                // 设置上级分销员ID到订单中
                order.setDistributorId(parentDistributor.getDistributorId());
                log.info("订单关联上级分销员ID: {}", parentDistributor.getDistributorId());
            } else {
                log.info("用户{}无上级分销员，订单不关联分销", userId);
            }
        } catch (Exception e) {
            log.warn("设置上级分销员时发生异常: {}", e.getMessage());
            // 即使检查失败，也不影响订单创建流程，订单将不关联分销
        }
    }


}
